#include<iostream>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<sys/types.h>        
#include<sys/socket.h>
#include<stdlib.h> //exit
#include<string.h> //memset
using namespace std;
//客户端
//客户端必须知道服务器的端口号和ip 所以客户端到时是这么启动程序的: ./udp_client server_ip sercer_port
//客户端要做的工作就是:从键盘获取输入,然后发送给服务端,然后再获取服务端的响应
//客户端只需要进行创建套接字然后就可以开始工作,不需要进行显示绑定
//客户端需要绑定,因为是网络通信,通信双方都需要找到对方,通过端口号+ip唯一标识网络当中的一台主机的一个进程
//但是客户端不需要显示绑定,因为客户端一旦绑定了一个固定的端口号,这个端口号就只能被这个客户端所使用,而且如果这个端口号被别人占用了,那么该客户端就不能启动了
//所以我们让OS帮我们绑定一个端口号,这样的话,只要端口号没有被耗尽,客户端永远能够启动

void Usage(std::string proc)
{
    cout << "Usage\n\t" << proc<<" server_ip "<<"server_port"<<endl;
    exit(1);
}
int main(int argc,char* argv[])
{
    if(argc != 3)
    {
        Usage(argv[0]);
    }
    int sock = socket(AF_INET,SOCK_DGRAM,0);
    if(sock < 0)
    {
        perror("socket");
        exit(2);
    }
    //填写服务端的网络相关信息
    struct sockaddr_in server;
    bzero(&server,sizeof(server));//先将server变量的内容清空
    server.sin_family = AF_INET;
    server.sin_port = htons(atoi(argv[2])); //端口号是字符串形式->整数 (主机序)-> 网络字节序
    server.sin_addr.s_addr = inet_addr(argv[1]);//字符串ip地址->整数ip地址
    socklen_t len = sizeof(server);
    //请求服务
    
    for(;;)
    {
        //1.获取用户输入
        char msg[1024] = {0};
        cout <<"请输入内容:  ";
        fgets(msg,sizeof(msg)-1,stdin);//从键盘stdin当中读取 ->会把\n也读到
        //2.把读取到的内容发送给服务端
        //hello\n\0 -> strlen得到的大小为6
        msg[strlen(msg) - 1 ] = '\0';//把\n位置置为0 
        
        sendto(sock,msg,strlen(msg),0,(struct sockaddr*)&server,len);//数据要发送到哪里,所以填入的是服务端的网络相关信息

        struct sockaddr_in tmp;//用于传参
        socklen_t len_tmp = sizeof(tmp);
        char buf[1024] = {0};
        ssize_t cnt = recvfrom(sock,buf,sizeof(buf)-1,0,(struct sockaddr*)&tmp,&len_tmp);
        if(cnt > 0)
        {
            buf[cnt] = 0;
            cout <<"server #" << buf << endl;
        }
        else 
        {
            perror("recvfrom");
        }
    } 
    return 0;
}